package dnl.confij;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Encapsulates a generic section based configuration. By section based, we mean
 * that any parameter exists in a section and the entire configuration contains
 * several sections.<br>
 * A <code>Configuration</code> object is populated by a
 * <code>ConfigurationSource</code>.
 * 
 * @author Daniel Or
 * 
 */
public class Configuration {

	protected Map<String, ConfigSection> sectionsMap;

	protected ConfigurationSource configSource;

	/**
	 * Creates an empty <code>Configuration</code>.
	 * 
	 */
	public Configuration() {
		this.sectionsMap = new HashMap<String, ConfigSection>();
	}

	/**
	 * Adds the given section.
	 * 
	 * @param section
	 *            a <code>ConfigSection</code> to add.
	 */
	public void addSection(ConfigSection section) {
		this.sectionsMap.put(section.getName(), section);
	}

	/**
	 * Removes the given section.
	 * 
	 * @param section
	 *            a <code>ConfigSection</code> to remove.
	 */
	public void removeSection(ConfigSection section) {
		this.sectionsMap.remove(section.getName());
	}

	/**
	 * Removes the given section.
	 * 
	 * @param sectionName
	 *            the name of the <code>ConfigSection</code>.
	 */
	public void removeSection(String sectionName) {
		this.sectionsMap.remove(sectionName);
	}

	/**
	 * Gets the section that has the corresponding name.
	 * 
	 * @param sectionName
	 *            the section's name.
	 * @return the corresponding <code>ConfigSection</code> or
	 *         <code>null</code> if none exists.
	 */
	public ConfigSection getSection(String sectionName) {
		return sectionsMap.get(sectionName);

	}

	/**
	 * Gets the section that has the corresponding name.
	 * 
	 * @param sectionName
	 *            the section's name.
	 * @return the corresponding <code>ConfigSection</code>. if none exists,
	 *         a new one is created.
	 */
	public ConfigSection getOrCreateSection(String sectionName) {
		ConfigSection configSection = sectionsMap.get(sectionName);
		if (configSection == null) {
			configSection = new ConfigSection(sectionName);
			addSection(configSection);
		}
		return configSection;
	}

	/**
	 * Gets all sections.
	 * 
	 * @return a <code>Collection</code> containing all sections.
	 */
	public Collection<ConfigSection> getSections() {
		return sectionsMap.values();
	}

	/**
	 * Gets the source that populated this <code>Configuration</code>.
	 * 
	 * @return the <code>ConfigurationSource</code> that populated this
	 *         <code>Configuration</code>.
	 */
	public ConfigurationSource getSource() {
		return configSource;
	}

	/**
	 * Loads/Reloads the configuration from it's source.
	 * 
	 * @throws ConfigException
	 *             if any error happens upon loading.
	 */
	public void loadConfiguration() throws ConfigException {
		configSource.loadConfiguration(this);
	}

	/**
	 * Saves the configuration to it's source.
	 * 
	 * @throws ConfigException
	 *             if any error happens upon saving.
	 */
	public void saveConfiguration() throws ConfigException {
		configSource.saveConfiguration(this);
	}
}
